/*
 * CMediaSourceFramer.cpp
 *
 *  Created on: 2019年1月9日
 *      Author: terry
 */

#include "CMediaSourceFramer.h"
#include "FfmpegUtil.h"
#include <algorithm>
#include <utility>
#include <deque>
#include "CLog.h"


#undef MAX



namespace av
{

CMediaSourceFramer::CMediaSourceFramer():
	m_mediaSource(),
	m_pts(),
	m_scale(1.0f),
	m_beginPts(),
	m_pktQueue(),
    m_curTime()
{
}

CMediaSourceFramer::~CMediaSourceFramer()
{
	close();
}

bool CMediaSourceFramer::open(MediaSourcePtr& source, int64_t pts)
{
	m_mediaSource = source;
	m_pts = pts;
	m_pktQueue.clear();

	int64_t beginPts = std::max((pts - SEEK_STEP), (int64_t)0);
	readFrames(beginPts, m_pts);
	m_beginPts = beginPts;

	return true;
}

void CMediaSourceFramer::close()
{
	m_mediaSource.reset();
	m_pktQueue.clear();
	m_pts = 0;
	m_beginPts = 0;
}

int CMediaSourceFramer::read(AVPacketPtr& pkt)
{
	if (m_pktQueue.size() <= 1 && m_beginPts > 0)
	{
		int64_t endPts = m_beginPts;
		int64_t beginPts = std::max((endPts - SEEK_STEP), (int64_t)0);
		readFrames(beginPts, endPts);
		m_beginPts = beginPts;
	}

	pkt = m_pktQueue.pop();
	if (!pkt)
	{
		return AVERROR_EOF;
	}

    m_curTime = pkt->pos;

	return 0;
}

void CMediaSourceFramer::setScale(float scale)
{
	if (scale <= 0)
	{
		return;
	}

	m_scale = scale;

	m_mediaSource->setScale(scale);
}

int CMediaSourceFramer::readFrames(int64_t beginPts, int64_t endPts)
{
	std::deque< AVPacketPtr > packets;

	int count = 0;
	int rc = m_mediaSource->seek(beginPts/1000);
	while (true)
	{
		AVPacketPtr pkt(new AVPacket(), ffmpeg::PacketDeleter());
		av_init_packet(pkt.get());
		int ret = m_mediaSource->read(*pkt.get());
		if (ret != 0)
		{
			break;
		}

		if (pkt->stream_index != MEDIA_TYPE_VIDEO || ((pkt->flags & AV_PKT_FLAG_KEY) == 0))
		{
			continue;
		}

		if (pkt->pts >= endPts)
		{
			break;
		}

		//CLog::info("CMediaSourceFramer. pkt.pts: %lld\n", pkt->pts/1000, (m_pts - pkt->pts)/1000);

        pkt->pos = pkt->pts;

		pkt->pts = m_pts - pkt->pts;
		pkt->dts = m_pts - pkt->dts;

		packets.push_front(pkt);
		
		count++;
	}

	for (size_t i = 0; i < packets.size(); i++)
	{
		m_pktQueue.push(packets[i]);
	}

	return count;
}

int64_t CMediaSourceFramer::getTime()
{
    return m_curTime;
}


} /* namespace av */
